/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Criptografia;

/**
 *
 * @author larissa
 */
public class Conversion {
    private static String [] hexDigits = {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};

    // Convert a byte to a hexadecimal String
    public static String byteToHexString(byte b) {
        int n = b;
        if(n < 0) n = 256 + n;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits [d1]+hexDigits [d2];
    }

    // Convert a byte array to a hexadecimal String
    public static String byteArrayToHexString(byte [] b) {
        String result = "";
        for(int i=0;i<b.length;++i)
            result += byteToHexString(b [i]);
        return result;
    }

    // Convert a byte array to a base 64 string (see RFC 1421)
    public static String byteArrayToBase64String(byte [] b, int len) {
        String s = "";
        // Organize into three byte groups and convert
        int n = len / 3;
        int m = len % 3;
        for(int i=0; i<n; ++i) {
            int j = i*3;
            s += toBase64(b [j],b [j+1],b [j+2]);
        }
        if(m == 1)
            s += toBase64(b [len-1]);
        else if(m==2)
            s += toBase64(b [len-2],b [len-1]);

        // Insert a new line every 64 characters
        String result = "";
        len = s.length();
        n = len / 64;
        m = len % 64;

        for(int i=0; i<n; ++i) {
            result += s.substring(i*64,(i+1)*64) + "\n";
        }

        if(m > 0)
            result += s.substring(n*64,len) + "\n";
        return result;
    }

    // Convert a byte array to a base 64 string (see RFC 1421)
    public static String byteArrayToBase64String(byte [] b) {
        return byteArrayToBase64String(b,b.length);
    }

    // Perform the base64 transformation
    private static String toBase64(byte b1, byte b2, byte b3) {
        int [] digit = new int [4];
        digit [0] = (b1 & 0xFC) >>> 2;
        digit [1] = (b1 & 0x03) << 4;
        digit [1] |= (b2 & 0xF0) >> 4;
        digit [2] = (b2 & 0x0F) << 2;
        digit [2] |= (b3 & 0xC0) >> 6;
        digit [3] = (b3 & 0x3F);
        String result = "";
        for(int i=0;i<digit.length;++i)
            result += base64Digit(digit [i]);
        return result;
    }

    // Perform a padded base64 transformation
    private static String toBase64(byte b1, byte b2) {
        int [] digit = new int [3];
        digit [0] = (b1 & 0xFC) >>> 2;
        digit [1] = (b1 & 0x03) << 4;
        digit [1] |= (b2 & 0xF0) >> 4;
        digit [2] = (b2 & 0x0F) << 2;
        String result = "";
        for(int i=0;i<digit.length;++i)
            result += base64Digit(digit [i]);
        result += "=";
        return result;
    }

    // Perform a padded base64 transformation
    private static String toBase64(byte b1) {
        int [] digit = new int [2];
        digit [0] = (b1 & 0xFC) >>> 2;
        digit [1] = (b1 & 0x03) << 4;
        String result = "";
        for(int i=0;i<digit.length;++i)
            result += base64Digit(digit [i]);
        result += "==";
        return result;
    }

    private static char base64Digit(int i) {
        if(i<26)
            return (char) ('A' + i);

        if(i<52)
            return (char) ('a' + (i - 26));

        if(i<62)
            return (char) ('0' + (i - 52));

        if(i == 62)
            return '+';
        else
            return '/';
    }

    // Convert a base 64 string to a byte array (see RFC 1421)
    public static byte [] base64StringToByteArray(String s) throws NumberFormatException {
        String t = "";
        for(int i=0;i<s.length();++i) {
            char c = s.charAt(i);

            if(c == '\n')
                continue;

            else if((c>='A' && c<='Z') ||
                    (c>='a' && c<='z') ||
                    (c>='0' && c<='9') ||
                    c=='+' || c=='/')
                t += c;
            else if(c=='=')
                break;
            else
                throw new NumberFormatException();
        }

        int len = t.length();
        int n = 3*(len/4);

        switch(len % 4) {
            case 1:
                throw new NumberFormatException();
            case 2:
                len += 2;
                n += 1;
                t += "==";
                break;
            case 3:
                ++len;
                n += 2;
                t += "=";
                break;
        }

        byte [] b = new byte [n];

        for(int i=0; i < len/4; ++i) {
            byte [] temp = base64ToBytes(t.substring(4*i,4*(i+1)));
            for(int j=0;j<temp.length;++j) {
                b [3*i+j] = temp [j];
            }
        }
        return b;
    }

    private static byte [] base64ToBytes(String s) {
        int len = 0;
        for(int i=0;i<s.length();++i)
            if(s.charAt(i) != '=') ++len;

        int [] digit = new int [len];
        for(int i=0;i<len;++i) {
            char c = s.charAt(i);
            if(c>='A' && c<='Z')
                digit [i] = c - 'A';
            else if(c>='a' && c<='z')
                digit [i] = c - 'a' + 26;
            else if(c>='0' && c<='9')
                digit [i] = c - '0' + 52;
            else if(c=='+')
                digit [i] = 62;
            else if(c=='/')
                digit [i] = 63;
        }

        byte [] b = new byte [len-1];
        switch(len) {
            case 4:
                b [2] = (byte) ((((digit [2]) & 0x03) << 6) | digit [3]);
            case 3:
                b [1] = (byte) ((((digit [1]) & 0x0F) << 4) | ((digit [2] & 0x3C) >>> 2));
            case 2:
                b [0] = (byte) ((digit [0] << 2) | ((digit [1] & 0x30) >>> 4));
        }
        return b;
    }
}